package lmh.example.exam2_2;


import android.opengl.GLSurfaceView;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class MyRenderer implements GLSurfaceView.Renderer {
    float[] triangleData = new float[]{     // 三角形顶点位置数据
            0.1f, 0.6f, 0.0f, // 上顶点
            -0.3f, 0.0f, 0.0f, // 左下顶点
            0.3f, 0.1f, 0.0f  // 右下顶点
    };
    int[] triangleColor = new int[]{        // 三角形顶点颜色数据
            65535, 0, 0, 0, // 上顶点红色
            0, 65535, 0, 0, // 左顶点绿色
            0, 0, 65535, 0 // 右顶点蓝色
    };
    // 正方形顶点位置数据
    float[] rectData = new float[]{
            0.4f, 0.4f, 0.0f, // 右上顶点
            0.4f, -0.4f, 0.0f, // 右下顶点
            -0.4f, 0.4f, 0.0f, // 左上顶点
            -0.4f, -0.4f, 0.0f // 左下顶点
    };
    // 正方形顶点颜色数据
    int[] rectColor = new int[]{
            0, 65535, 0, 0,
            0, 0, 65535, 0,
            65535, 0, 0, 0,
            65535, 65535, 0, 0
    };
    // 依然是正方形的4个顶点，只是顺序交换一下
    float[] rectData2 = new float[]{
            -0.4f, 0.4f, 0.0f, // 左上顶点
            0.4f, 0.4f, 0.0f, // 右上顶点
            0.4f, -0.4f, 0.0f, // 右下顶点
            -0.4f, -0.4f, 0.0f // 左下顶点
    };
    float[] pentacle = new float[]{         // 五边形顶点位置数据
            0.3f, 0.3f, 0.0f,
            -0.2f, 0.3f, 0.0f,
            0.4f, 0.0f, 0.0f,
            -0.3f, 0.0f, 0.0f,
            -0.1f, -0.3f, 0.0f
    };
    FloatBuffer triangleDataBuffer;
    IntBuffer triangleColorBuffer;
    FloatBuffer rectDataBuffer;
    IntBuffer rectColorBuffer;
    FloatBuffer rectDataBuffer2;
    FloatBuffer pentacleBuffer;

    public MyRenderer() {
        // 将顶点位置数据数组转换成FloatBuffer
        triangleDataBuffer = floatBufferUtil(triangleData);
        rectDataBuffer = floatBufferUtil(rectData);
        rectDataBuffer2 = floatBufferUtil(rectData2);
        pentacleBuffer = floatBufferUtil(pentacle);
        // 将顶点颜色数据数组转换成IntBuffer
        triangleColorBuffer = intBufferUtil(triangleColor);
        rectColorBuffer = intBufferUtil(rectColor);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        // 关闭抗抖动
        gl.glDisable(GL10.GL_DITHER);
        // 设置系统对透视进行修正
        gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
        // 设置清屏色
        gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        // 设置阴影模式为：平滑SMOOTH
        gl.glShadeModel(GL10.GL_SMOOTH);
        // 启用深度测试
        gl.glEnable(GL10.GL_DEPTH_TEST);
        // 设置深度测试的类型
        gl.glDepthFunc(GL10.GL_LEQUAL);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        // 设置视窗的大小及位置
        gl.glViewport(0, 0, width, height);
        // 将当前矩阵模式设为：投影矩阵
        gl.glMatrixMode(GL10.GL_PROJECTION);
        // 加载单位矩阵
        gl.glLoadIdentity();
        // 计算透视视窗的宽度、高度比
        float ratio = (float) width / height;
        // 调用此方法设置视景体的空间大小
        // 原点在相机位置
        // 视景体的近平面的宽高比和视口的宽高比保持一致，可以使得投影不走样。
        gl.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
    }

    // 绘制图形的方法
    @Override
    public void onDrawFrame(GL10 gl) {
        // 清除屏幕缓存和深度缓存
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        // 启用顶点坐标数据
        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        // 启用顶点颜色数据
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
        // 设置当前矩阵模式为：模型视图矩阵
        gl.glMatrixMode(GL10.GL_MODELVIEW);

        // --------------------绘制第一个图形（三角形）---------------------
        // 加载单位矩阵
        gl.glLoadIdentity();
        // 对图像进行平移操作（ -10.0<=z坐标<-1.0 ，这样三角形将位于视景体内，可以显示出来）
        gl.glTranslatef(-0.32f, 0.35f, -1.8f);
        // 图形靠近近平面，则投影图形呈现“近大”效果
//        gl.glTranslatef(-0.32f, 0.35f, -1.1f);
        // 图形远离近平面，则投影图形呈现“远小”效果
//        gl.glTranslatef(-0.32f, 0.35f, -9.9f);
        // 设置顶点的位置数据
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, triangleDataBuffer);
        // 设置顶点的颜色数据
        gl.glColorPointer(4, GL10.GL_FIXED, 0, triangleColorBuffer);
        // 根据顶点数据绘制三角形
        gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);

        // --------------------绘制第二个图形（两个三角形，组成了正方形）---------------------
        // 重置当前的模型视图矩阵
        gl.glLoadIdentity();
        // 对图像进行平移操作
        gl.glTranslatef(0.6f, 0.8f, -1.8f);
        // 设置顶点的位置数据
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, rectDataBuffer);
        // 设置顶点的颜色数据
        gl.glColorPointer(4, GL10.GL_FIXED, 0, rectColorBuffer);
        // 根据顶点数据绘制三角形带
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);

        // --------------------绘制第三个图形（两个三角形，但未组成正方形）---------------------
        // 重置当前的模型视图矩阵
        gl.glLoadIdentity();
        // 对图像进行平移操作
        gl.glTranslatef(-0.4f, -0.5f, -1.8f);
        // 设置顶点的位置数据（依然使用之前的顶点颜色）
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, rectDataBuffer2);
        // 根据顶点数据绘制三角形带
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);

        // --------------------绘制第四个图形（三个三角形，组成了五边形）---------------------
        // 重置当前的模型视图矩阵
        gl.glLoadIdentity();
        // 对图像进行平移操作
        gl.glTranslatef(0.4f, -0.5f, -1.5f);
        // 设置使用纯色填充
        gl.glColor4f(1.0f, 0.2f, 0.2f, 0.0f);  // ②
        // 禁用顶点颜色数组
        gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
        // 设置顶点的位置数据
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, pentacleBuffer);
        // 根据顶点数据绘制三角形带
        gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 5);

        // 绘制结束
        gl.glFinish();
        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    }

    // 定义一个工具方法，将float[]数组转换为OpenGL ES所需的FloatBuffer
    private FloatBuffer floatBufferUtil(float[] arr) {
        FloatBuffer mBuffer;
        // 初始化ByteBuffer，长度为arr数组的长度*4，因为一个float占4字节
        ByteBuffer qbb = ByteBuffer.allocateDirect(arr.length * 4);
        // 数组排列用nativeOrder
        qbb.order(ByteOrder.nativeOrder());
        mBuffer = qbb.asFloatBuffer();
        mBuffer.put(arr);
        mBuffer.position(0);
        return mBuffer;
    }

    // 定义一个工具方法，将int[]数组转换为OpenGL ES所需的IntBuffer
    private IntBuffer intBufferUtil(int[] arr) {
        IntBuffer mBuffer;
        // 初始化ByteBuffer，长度为arr数组的长度*4，因为一个int占4字节
        ByteBuffer qbb = ByteBuffer.allocateDirect(arr.length * 4);
        // 数组排列用nativeOrder
        qbb.order(ByteOrder.nativeOrder());
        mBuffer = qbb.asIntBuffer();
        mBuffer.put(arr);
        mBuffer.position(0);
        return mBuffer;
    }
}